package com.example.mail.accountservice.rest;


import com.alibaba.csp.sentinel.annotation.SentinelResource;
import com.alibaba.csp.sentinel.slots.block.BlockException;
import com.example.account.dto.AccountDTO;
import com.example.account.feign.AccountFeign;
import com.example.product.feign.ProductFeign;
import com.example.rest.RestBody;
import com.example.rest.RestCode;
import lombok.AllArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import org.springframework.web.bind.annotation.RestController;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.example.mail.accountservice.service.AccountService;

import com.example.mail.accountservice.entity.Account;
import org.springframework.web.bind.annotation.*;


/**
 * <p>
 *  前端控制器
 * </p>
 *
 * @author zhou
 * @since 2022-01-10
 */
@AllArgsConstructor
@RestController
public class AccountController implements AccountFeign {
    private static final Logger logger = LoggerFactory.getLogger(AccountController.class);

    private final AccountService accountService;
    private final ProductFeign productFeign;

    @GetMapping("/account/product/{code}")
    public RestBody<?> getProduct(@PathVariable(value = "code")String code){
        return this.productFeign.getByCode(code);
    }

    @Override
    public RestBody<?> deductAmount(@RequestBody AccountDTO amountDTO){
        String code = amountDTO.getCode();
        Account one = this.accountService.getOne(new LambdaQueryWrapper<Account>().eq(Account::getAccountCode, code));
        if(one != null && one.getAmount().compareTo(amountDTO.getAmount()) >= 0){
            one.setAmount(one.getAmount().subtract(amountDTO.getAmount()));
            this.accountService.updateById(one);
            return RestBody.ok();
        }
        throw new RuntimeException("account is not existed or amount is not enough");
    }

    /**
     * 逻辑删除一条 实体，
     * 注意当且仅当调用 mybatis plus 内置方法时可以自动处理
     * @param id 资源对应id主键
     * @return Rest
     */
    @DeleteMapping("/{id}")
    public RestBody<?> delete(@PathVariable("id")  Long id){
        boolean removed = this.accountService.removeById(id);
        //Restful风格建议，无可操作数据时，返回404资源未找到提示
        return removed ? RestBody.ok() : RestBody.fail(RestCode.RESOURCE_NOT_FOUND);
    }

    @Override
    @SentinelResource(value = "getByCode", blockHandler = "blockHandler")
    public RestBody<?> getByCode(String code) {
        Account one = this.accountService.getOne(new LambdaQueryWrapper<Account>().eq(Account::getAccountCode,code));
        return RestBody.ok(one);
    }

    @GetMapping("/account/query/sql")
    public RestBody<?> getOneBySQL(){
        return RestBody.ok(this.accountService.queryBySQL());
    }

    public RestBody<?> blockHandler(String code, BlockException exception){
        logger.info("flow exception:{}",exception.getClass().getCanonicalName());
        return RestBody.fail(RestCode.FLOW_LIMIT);
    }

    @Override
    public RestBody<?> addOrUpdate(@RequestBody AccountDTO accountDTO) {
        Account account = new Account();
        if(account.getId() != null){
            this.accountService.updateById(account);
        }else{
            this.accountService.save(account);
        }
        return RestBody.ok();
    }

    @GetMapping("/admin/test")
    public RestBody<?> securityTest(){
        return RestBody.ok("OK");
    }
}

